using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Lazy.Captcha.Core.RateLimit
{
    /// <summary>
    /// 基于内存的频率限制器
    /// </summary>
    public class MemoryRateLimiter : IRateLimiter
    {
        private readonly ConcurrentDictionary<string, RateLimitEntry> _cache = new();

        /// <summary>
        /// 检查是否允许请求
        /// </summary>
        public bool IsAllowed(string key, int windowSeconds, int maxRequests)
        {
            var now = DateTime.UtcNow;
            var windowStart = now.AddSeconds(-windowSeconds);

            var entry = _cache.AddOrUpdate(key, 
                new RateLimitEntry { Count = 1, WindowStart = now },
                (k, existing) =>
                {
                    // 如果当前时间超出了时间窗口，重置计数器
                    if (existing.WindowStart < windowStart)
                    {
                        return new RateLimitEntry { Count = 1, WindowStart = now };
                    }
                    
                    // 在时间窗口内，增加计数
                    existing.Count++;
                    return existing;
                });

            // 清理过期的条目（简单的清理策略）
            CleanupExpiredEntries(windowSeconds);

            return entry.Count <= maxRequests;
        }

        /// <summary>
        /// 异步检查是否允许请求
        /// </summary>
        public Task<bool> IsAllowedAsync(string key, int windowSeconds, int maxRequests)
        {
            return Task.FromResult(IsAllowed(key, windowSeconds, maxRequests));
        }

        /// <summary>
        /// 获取剩余请求次数
        /// </summary>
        public int GetRemainingRequests(string key, int windowSeconds, int maxRequests)
        {
            if (!_cache.TryGetValue(key, out var entry))
            {
                return maxRequests;
            }

            var now = DateTime.UtcNow;
            var windowStart = now.AddSeconds(-windowSeconds);

            // 如果条目已过期，返回最大请求次数
            if (entry.WindowStart < windowStart)
            {
                return maxRequests;
            }

            return Math.Max(0, maxRequests - entry.Count);
        }

        /// <summary>
        /// 获取下次重置时间
        /// </summary>
        public DateTime? GetResetTime(string key, int windowSeconds)
        {
            if (!_cache.TryGetValue(key, out var entry))
            {
                return null;
            }

            return entry.WindowStart.AddSeconds(windowSeconds);
        }

        /// <summary>
        /// 清理过期的条目
        /// </summary>
        private void CleanupExpiredEntries(int windowSeconds)
        {
            var cutoff = DateTime.UtcNow.AddSeconds(-windowSeconds * 2); // 保留双倍时间窗口的数据
            var keysToRemove = new List<string>();

            foreach (var kvp in _cache)
            {
                if (kvp.Value.WindowStart < cutoff)
                {
                    keysToRemove.Add(kvp.Key);
                }
            }

            foreach (var key in keysToRemove)
            {
                _cache.TryRemove(key, out _);
            }
        }

        /// <summary>
        /// 频率限制条目
        /// </summary>
        private class RateLimitEntry
        {
            public int Count { get; set; }
            public DateTime WindowStart { get; set; }
        }
    }
}
